﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using log4net;
using Arcanea.NetworkEngine.Concrete;
using Arcanea.NetworkEngine.Abstract;
using Arcanea.NetworkEngine.Abstract.Engines;
using System.Reflection;
using log4net.Appender;
using log4net.Layout;
using log4net.Repository;
using log4net.Repository.Hierarchy;
using log4net.Core;

namespace Arcanea.MMORPGServer
{
    public partial class ServerForm : Form
    {
        private Thread th = null;
        private List<ThreadItem> allClients = new List<ThreadItem>();
        private bool ThreadGoOn = false;
        private int port = 0;
        private MemoryAppender memoryAppender = new MemoryAppender();

        protected static readonly ILog logger = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);

        #region Constructeur
        public ServerForm()
        {
            InitializeComponent();

            Hierarchy loggerHierarchy = LogManager.GetRepository() as Hierarchy;

            memoryAppender = new MemoryAppender();
            memoryAppender.Name = "MemoryAppender";
            memoryAppender.Layout = new PatternLayout("%5p [%d] [%t] %C{1} - %m%n");
            memoryAppender.Threshold = Level.Debug;
            loggerHierarchy.Root.AddAppender(memoryAppender);
            memoryAppender.ActivateOptions();


            ////Configure memory appender
            //Hierarchy loggerHierarchy = LogManager.GetRepository() as Hierarchy;
            //if (loggerHierarchy != null)
            //{
            //    memoryAppender = loggerHierarchy.Root.GetAppender("MemoryAppender") as MemoryAppender;
            //}
            //end of config

        }
        #endregion



        private void buttonLaunchThread_Click(object sender, EventArgs e)
        {            
            lock (allClients)
            {
                ThreadGoOn = true;
                port = (int)numericUpDownPort.Value;
            }
            th = new Thread(new ThreadStart(MainThreadCode));
            th.Start();
            buttonLaunchThread.Enabled = false;
            numericUpDownPort.Enabled = false;
            buttonStopServer.Enabled = true;
        }

        private void buttonStopServer_Click(object sender, EventArgs e)
        {
            lock (allClients)
            {
                ThreadGoOn = false;
            }
            while (th.ThreadState == ThreadState.Running)
            {
            }
            buttonLaunchThread.Enabled = true;
            numericUpDownPort.Enabled = true;
            buttonStopServer.Enabled = false;
        }

        #region Main server code in a thread function

        /// <summary>
        /// Lancement du serveur
        /// </summary>
        private void MainThreadCode()
        {
            int port = 666;
            INetEngine neServer = new TCPServerNetEngine(port);
            NetInformationContainer infos = null;

            bool threadGoOnLocal = false;
            lock (allClients)
            {
                threadGoOnLocal = ThreadGoOn;
            }
            int counter = 0;
            LoggThisInfo("Server started in port " + port);
            while (threadGoOnLocal)
            {
                counter = (counter + 1) % 1000;
                infos = neServer.ProtocoleEngine.AcceptedConnection();
                if (infos == null)
                {
                    ///Waiting 1 sec to prevent infinite loop
                    System.Threading.Thread.Sleep(1000);
                }
                else
                {
                    //Lancement du thread
                    ThreadItem thi = new ThreadItem(infos);
                    thi.Start();
                    allClients.Add(thi);
                    LoggThisInfo("One client added ");
                }

                if (counter == 0)
                {
                    CleanAllClients();
                }
                lock (allClients)
                {
                    threadGoOnLocal = ThreadGoOn;
                }
            }
            neServer.Close();
            LoggThisInfo("Server closed");

            //Mise en place des classes TCP et UDP.
            //lancement du serveur TCP
            //Lancement du retraitement des paquets

            //En cas de fermeture, Signaler la fermeture et attendre la fin des threads
        }

        private void LoggThisInfo(string text)
        {
            logger.Info(text);
        }

        private void CleanAllClients()
        {
            int i = 0;
            while (i < allClients.Count)
            {
                if (allClients[i].IsActive())
                {
                    i++;
                }
                else
                {
                    allClients.RemoveAt(i);
                }
            }
        }


        #endregion

        private void timerUpdateAppender_Tick(object sender, EventArgs e)
        {
            LoggingEvent[] le = memoryAppender.GetEvents();
            foreach (LoggingEvent l in le)
            {
                richTextBoxLog.Text += l.RenderedMessage + Environment.NewLine;
            }
            memoryAppender.Clear();
        }

    }
}
